home *** CD-ROM | disk | FTP | other *** search
/ 3D GFX / 3D GFX.iso / amiutils / i_l / irit5 / triv_lib / triveval.c < prev    next >
C/C++ Source or Header  |  1995-12-30  |  19KB  |  549 lines

  1. /******************************************************************************
  2. * TrivEval.c - tri-variate function handling routines - evaluation routines.  *
  3. *******************************************************************************
  4. * Written by Gershon Elber, Sep. 94.                          *
  5. ******************************************************************************/
  6.  
  7. #include <string.h>
  8. #include "triv_loc.h"
  9.  
  10. /*****************************************************************************
  11. * DESCRIPTION:                                                               M
  12. * Evaluates the given tensor product trivariate at a given point, by         M
  13. * extracting an isoparamteric surface along w and evaluating (u,v) in it.    M
  14. *   Not very efficient way to evaluate the tri-variate...             M
  15. *                                         V
  16. *           +-----------------------+                         V
  17. *       W  /                       /|                         V
  18. *      /  /                       / |                         V
  19. *     /  /    U -->         /  |                         V
  20. *       +-----------------------+   |  Control tri-variate mesh orientation. V
  21. *   V | |P0                 Pi-1|   +                         V
  22. *     v    |Pi                P2i-1|  /                         V
  23. *    |            | /                         V
  24. *    |Pn-i            Pn-1|/                           V
  25. *    +-----------------------+                         V
  26. *                                                                            *
  27. * PARAMETERS:                                                                M
  28. *   TV:       To evaluate at given (u, v, w) parametric location.            M
  29. *   u, v, w:  Parametric location to evaluate TV at.                         M
  30. *                                                                            *
  31. * RETURN VALUE:                                                              M
  32. *   CagdRType *:  A vector holding all the coefficients of all components    M
  33. *                 of the trivariate's point type. If for example trivariate  M
  34. *                 point type is P2, the W, X, and Y will be saved in the     M
  35. *                 first three locations of the returned vector. The first    M
  36. *                 location (index 0) of the returned vector is reserved for  M
  37. *                 the rational coefficient W and XYZ always starts at second M
  38. *                 location of the returned vector (index 1).                 M
  39. *                                                                            *
  40. * KEYWORDS:                                                                  M
  41. *   TrivTVEval, evaluation, trivariates                                      M
  42. *****************************************************************************/
  43. CagdRType *TrivTVEval(TrivTVStruct *TV, CagdRType u, CagdRType v, CagdRType w)
  44. {
  45.     static CagdSrfStruct
  46.     *IsoSubSrf = NULL;
  47.     CagdRType *Pt, *WBasisFunc, UMin, UMax, VMin, VMax, WMin, WMax;
  48.     CagdBType
  49.     IsNotRational = !TRIV_IS_RATIONAL_TV(TV);
  50.     int k, UIndexFirst, VIndexFirst, WIndexFirst,
  51.     UOrder = TV -> UOrder,
  52.     VOrder = TV -> VOrder,
  53.     WOrder = TV -> WOrder,
  54.         ULength = TV -> ULength,
  55.         VLength = TV -> VLength,
  56.         WLength = TV -> WLength,
  57.     MaxCoord = CAGD_NUM_OF_PT_COORD(TV -> PType);
  58.  
  59.     /* The code below is optimized for Bspline trivariates. For Bezier    */
  60.     /* trivariate we have to process the entire data any way.             */
  61.     if (TRIV_IS_BEZIER_TV(TV))
  62.         return TrivTVEval2(TV, u, v, w);
  63.  
  64.     TrivTVDomain(TV, &UMin, &UMax, &VMin, &VMax, &WMin, &WMax);
  65.     if (u < UMin - EPSILON || u > UMax + EPSILON ||
  66.         v < VMin - EPSILON || v > VMax + EPSILON ||
  67.         w < WMin - EPSILON || w > WMax + EPSILON)
  68.         TRIV_FATAL_ERROR(TRIV_ERR_WRONG_DOMAIN);
  69.  
  70.     if (u > UMax - IRIT_EPSILON * 2)
  71.     u = UMax - IRIT_EPSILON * 2;
  72.     else if (u < UMin)
  73.         u = UMin;
  74.     if (v > VMax - IRIT_EPSILON * 2)
  75.     v = VMax - IRIT_EPSILON * 2;
  76.     else if (v < VMin)
  77.         v = VMin;
  78.     if (w > WMax - IRIT_EPSILON * 2)
  79.     w = WMax - IRIT_EPSILON * 2;
  80.     else if (w < WMin)
  81.         w = WMin;
  82.  
  83.     UIndexFirst = BspKnotLastIndexLE(TV -> UKnotVector, ULength + UOrder, u) -
  84.                                   (UOrder - 1);
  85.     VIndexFirst = BspKnotLastIndexLE(TV -> VKnotVector, VLength + VOrder, v) -
  86.                                   (VOrder - 1);
  87.     WBasisFunc = BspCrvCoxDeBoorBasis(TV -> WKnotVector, WOrder,
  88.                       WLength, w, &WIndexFirst);
  89.  
  90.     if (IsoSubSrf != NULL &&
  91.     (TV -> PType != IsoSubSrf -> PType ||
  92.      UOrder != IsoSubSrf -> UOrder ||
  93.      VOrder != IsoSubSrf -> VOrder)) {
  94.     /* The cached surface is not the proper type - release it. */
  95.     CagdSrfFree(IsoSubSrf);
  96.     IsoSubSrf = NULL;
  97.     }
  98.     if (IsoSubSrf == NULL) {
  99.         IsoSubSrf = BspSrfNew(UOrder, VOrder, UOrder, VOrder, TV -> PType);
  100.     }
  101.     CAGD_GEN_COPY(IsoSubSrf -> UKnotVector,
  102.           &TV -> UKnotVector[UIndexFirst],
  103.           sizeof(CagdRType) * UOrder * 2);
  104.     CAGD_GEN_COPY(IsoSubSrf -> VKnotVector,
  105.           &TV -> VKnotVector[VIndexFirst],
  106.           sizeof(CagdRType) * VOrder * 2);
  107.  
  108.     for (k = 0; k < UOrder; k++, UIndexFirst++) {
  109.     int n,
  110.         VIndexFirstTmp = VIndexFirst;
  111.  
  112.     for (n = 0; n < VOrder; n++, VIndexFirstTmp++) {
  113.         int l;
  114.  
  115.         for (l = IsNotRational; l <= MaxCoord; l++) {
  116.         int i;
  117.         CagdRType
  118.             *TVP = &TV -> Points[l][TRIV_MESH_UVW(TV,
  119.                               UIndexFirst,
  120.                               VIndexFirstTmp,
  121.                               WIndexFirst)],
  122.             *SrfP = &IsoSubSrf -> Points[l][CAGD_MESH_UV(IsoSubSrf,
  123.                                  k, n)];
  124.  
  125.         *SrfP = 0.0;
  126.         for (i = 0; i < WOrder; i++) {
  127.             *SrfP += WBasisFunc[i] * *TVP;
  128.             TVP += TRIV_NEXT_W(TV);
  129.         }
  130.         }
  131.     }
  132.     }
  133.  
  134.     Pt = BspSrfEvalAtParam(IsoSubSrf, u, v);
  135.  
  136.     return Pt;
  137. }
  138.  
  139. /*****************************************************************************
  140. * DESCRIPTION:                                                               M
  141. * Same as TrivTVEval2 above. Cleaner, but much less efficient.                 M
  142. *****************************************************************************/
  143. CagdRType *TrivTVEval2(TrivTVStruct *TV, CagdRType u, CagdRType v, CagdRType w)
  144. {
  145.     CagdRType *Pt;
  146.     CagdSrfStruct
  147.     *IsoSrf = TrivSrfFromTV(TV, u, TRIV_CONST_U_DIR);
  148.  
  149.     if (!TrivParamsInDomain(TV, u, v, w)) {
  150.     TRIV_FATAL_ERROR(TRIV_ERR_WRONG_DOMAIN);
  151.     return NULL;
  152.     }
  153.  
  154.     Pt = CagdSrfEval(IsoSrf, v, w);
  155.  
  156.     CagdSrfFree(IsoSrf);
  157.  
  158.     return Pt;
  159. }
  160.  
  161. /*****************************************************************************
  162. * DESCRIPTION:                                                               M
  163. * Extract an isoparametric surface out of the given tensor product         M
  164. * trivariate.                                          M
  165. *   Operations should favor the CONST_W_DIR, in which the extraction is         M
  166. * somewhat faster, if it is possible.                         M
  167. *                                                                            *
  168. * PARAMETERS:                                                                M
  169. *   TV:       To extract an isoparametric surface from at parameter value t  M
  170. *          in direction Dir.                             M
  171. *   t:        Parameter value at which to extract the isosurface.            M
  172. *   Dir:      Direction of isosurface extraction. Either U or V or W.        M
  173. *                                                                            *
  174. * RETURN VALUE:                                                              M
  175. *   CagdSrfStruct *:   A bivariate surface which is an isosurface of TV.     M
  176. *                                                                            *
  177. * KEYWORDS:                                                                  M
  178. *   TrivSrfFromTV, trivariates                                               M
  179. *****************************************************************************/
  180. CagdSrfStruct *TrivSrfFromTV(TrivTVStruct *TV,
  181.                  CagdRType t,
  182.                  TrivTVDirType Dir)
  183. {
  184.     CagdSrfStruct
  185.     *Srf = NULL;
  186.     CagdBType
  187.     IsNotRational = !TRIV_IS_RATIONAL_TV(TV);
  188.     int i, j, k, SrfLen,
  189.     MaxCoord = CAGD_NUM_OF_PT_COORD(TV -> PType);
  190.     CagdRType *SrfP, *TVP;
  191.  
  192.     if (!TrivParamInDomain(TV, t, Dir)) {
  193.     TRIV_FATAL_ERROR(TRIV_ERR_WRONG_DOMAIN);
  194.     return NULL;
  195.     }
  196.  
  197.     switch (Dir) {
  198.     case TRIV_CONST_U_DIR:
  199.         if (TV -> GType == TRIV_TVBSPLINE_TYPE) {
  200.         Srf = BspSrfNew(TV -> VLength, TV -> WLength,
  201.                 TV -> VOrder, TV -> WOrder,
  202.                 TV -> PType);
  203.         CAGD_GEN_COPY(Srf -> UKnotVector, TV -> VKnotVector,
  204.                   sizeof(CagdRType) * (TV -> VLength +
  205.                            TV -> VOrder));
  206.         CAGD_GEN_COPY(Srf -> VKnotVector, TV -> WKnotVector,
  207.                   sizeof(CagdRType) * (TV -> WLength +
  208.                            TV -> WOrder));
  209.         }
  210.         else {
  211.         Srf = BzrSrfNew(TV -> VLength, TV -> WLength, TV -> PType);
  212.         }
  213.         SrfLen = Srf -> ULength * Srf -> VLength;
  214.  
  215.         if (TV -> GType == TRIV_TVBSPLINE_TYPE) {
  216.         for (i = IsNotRational; i <= MaxCoord; i++) {
  217.             SrfP = Srf -> Points[i];
  218.             TVP = TV -> Points[i];
  219.             for (j = 0; j < SrfLen; j++) {
  220.             *SrfP++ = BspCrvEvalVecAtParam(TVP, TRIV_NEXT_U(TV),
  221.                                TV -> UKnotVector,
  222.                                TV -> UOrder,
  223.                                TV -> ULength,
  224.                                FALSE, t);
  225.             TVP += TRIV_NEXT_V(TV);
  226.             }
  227.         }
  228.         }
  229.         else {
  230.         for (i = IsNotRational; i <= MaxCoord; i++) {
  231.             SrfP = Srf -> Points[i];
  232.             TVP = TV -> Points[i];
  233.             for (j = 0; j < SrfLen; j++) {
  234.             *SrfP++ = BzrCrvEvalVecAtParam(TVP, TRIV_NEXT_U(TV),
  235.                                TV -> ULength, t);
  236.             TVP += TRIV_NEXT_V(TV);
  237.             }
  238.         }
  239.         }
  240.         break;
  241.     case TRIV_CONST_V_DIR:
  242.         if (TV -> GType == TRIV_TVBSPLINE_TYPE) {
  243.         Srf = BspSrfNew(TV -> ULength, TV -> WLength,
  244.                 TV -> UOrder, TV -> WOrder,
  245.                 TV -> PType);
  246.         CAGD_GEN_COPY(Srf -> UKnotVector, TV -> UKnotVector,
  247.                   sizeof(CagdRType) * (TV -> ULength +
  248.                            TV -> UOrder));
  249.         CAGD_GEN_COPY(Srf -> VKnotVector, TV -> WKnotVector,
  250.                   sizeof(CagdRType) * (TV -> WLength +
  251.                            TV -> WOrder));
  252.         }
  253.         else {
  254.         Srf = BzrSrfNew(TV -> ULength, TV -> WLength, TV -> PType);
  255.         }
  256.         SrfLen = Srf -> ULength * Srf -> VLength;
  257.  
  258.         if (TV -> GType == TRIV_TVBSPLINE_TYPE) {
  259.         for (k = 0, i = IsNotRational; i <= MaxCoord; i++) {
  260.             SrfP = Srf -> Points[i];
  261.             TVP = TV -> Points[i];
  262.             for (j = 0; j < SrfLen; j++) {
  263.             *SrfP++ = BspCrvEvalVecAtParam(TVP, TRIV_NEXT_V(TV),
  264.                                TV -> VKnotVector,
  265.                                TV -> VOrder,
  266.                                TV -> VLength,
  267.                                FALSE, t);
  268.             TVP += TRIV_NEXT_U(TV);
  269.             if (++k == TV -> ULength) {
  270.                 TVP += TRIV_NEXT_W(TV) - TRIV_NEXT_U(TV) * k;
  271.                 k = 0;
  272.             }
  273.             }
  274.         }
  275.         }
  276.         else {
  277.         for (k = 0, i = IsNotRational; i <= MaxCoord; i++) {
  278.             SrfP = Srf -> Points[i];
  279.             TVP = TV -> Points[i];
  280.             for (j = 0; j < SrfLen; j++) {
  281.             *SrfP++ = BzrCrvEvalVecAtParam(TVP, TRIV_NEXT_V(TV),
  282.                                TV -> VLength, t);
  283.             TVP += TRIV_NEXT_U(TV);
  284.             if (++k == TV -> ULength) {
  285.                 TVP += TRIV_NEXT_W(TV) - TRIV_NEXT_U(TV) * k;
  286.                 k = 0;
  287.             }
  288.             }
  289.         }
  290.         }
  291.         break;
  292.     case TRIV_CONST_W_DIR:
  293.         if (TV -> GType == TRIV_TVBSPLINE_TYPE) {
  294.         Srf = BspSrfNew(TV -> ULength, TV -> VLength,
  295.                 TV -> UOrder, TV -> VOrder,
  296.                 TV -> PType);
  297.         CAGD_GEN_COPY(Srf -> UKnotVector, TV -> UKnotVector,
  298.                   sizeof(CagdRType) * (TV -> ULength +
  299.                            TV -> UOrder));
  300.         CAGD_GEN_COPY(Srf -> VKnotVector, TV -> VKnotVector,
  301.                   sizeof(CagdRType) * (TV -> VLength +
  302.                            TV -> VOrder));
  303.         }
  304.         else {
  305.         Srf = BzrSrfNew(TV -> ULength, TV -> VLength, TV -> PType);
  306.         }
  307.         SrfLen = Srf -> ULength * Srf -> VLength;
  308.  
  309.         if (TV -> GType == TRIV_TVBSPLINE_TYPE) {
  310.         for (i = IsNotRational; i <= MaxCoord; i++) {
  311.             SrfP = Srf -> Points[i];
  312.             TVP = TV -> Points[i];
  313.             for (j = 0; j < SrfLen; j++) {
  314.             *SrfP++ = BspCrvEvalVecAtParam(TVP, TRIV_NEXT_W(TV),
  315.                                TV -> WKnotVector,
  316.                                TV -> WOrder,
  317.                                TV -> WLength,
  318.                                FALSE, t);
  319.             TVP += TRIV_NEXT_U(TV);
  320.             }
  321.         }
  322.         }
  323.         else {
  324.         for (i = IsNotRational; i <= MaxCoord; i++) {
  325.             SrfP = Srf -> Points[i];
  326.             TVP = TV -> Points[i];
  327.             for (j = 0; j < SrfLen; j++) {
  328.             *SrfP++ = BzrCrvEvalVecAtParam(TVP, TRIV_NEXT_W(TV),
  329.                                TV -> WLength, t);
  330.             TVP += TRIV_NEXT_U(TV);
  331.             }
  332.         }
  333.         }
  334.         break;
  335.     default:
  336.         TRIV_FATAL_ERROR(TRIV_ERR_WRONG_DOMAIN);
  337.         break;
  338.     }
  339.     return Srf;
  340. }
  341.  
  342. /*****************************************************************************
  343. * DESCRIPTION:                                                               M
  344. * Extract a bivariate surface out of the given trivariate's mesh.         M
  345. *   The provided (zero based) Index specifies which Index to extract.        M
  346. *                                                                            *
  347. * PARAMETERS:                                                                M
  348. *   TV:        Trivariate to extract a bivariate surface out of its mesh.    M
  349. *   Index:     Index of row/column/level of TV's mesh in direction Dir.      M
  350. *   Dir:       Direction of isosurface extraction. Either U or V or W.       M
  351. *                                                                            *
  352. * RETURN VALUE:                                                              M
  353. *   CagdSrfStruct *:   A bivariate surface which was extracted from TV's     M
  354. *                      Mesh. This surface is not necessarily on TV.          M
  355. *                                                                            *
  356. * KEYWORDS:                                                                  M
  357. *   TrivSrfFromMesh, trivariates                                             M
  358. *****************************************************************************/
  359. CagdSrfStruct *TrivSrfFromMesh(TrivTVStruct *TV,
  360.                    int Index,
  361.                    TrivTVDirType Dir)
  362. {
  363.     CagdSrfStruct
  364.     *Srf = NULL;
  365.     CagdBType
  366.     IsNotRational = !TRIV_IS_RATIONAL_TV(TV);
  367.     int i, j, k, SrfLen,
  368.     MaxCoord = CAGD_NUM_OF_PT_COORD(TV -> PType);
  369.     CagdRType *SrfP, *TVP;
  370.  
  371.     switch (Dir) {
  372.     case TRIV_CONST_U_DIR:
  373.         if (Index >= TV -> ULength || Index < 0)
  374.         TRIV_FATAL_ERROR(TRIV_ERR_INDEX_NOT_IN_MESH);
  375.  
  376.         if (TV -> GType == TRIV_TVBSPLINE_TYPE) {
  377.         Srf = BspSrfNew(TV -> VLength, TV -> WLength,
  378.                 TV -> VOrder, TV -> WOrder,
  379.                 TV -> PType);
  380.         CAGD_GEN_COPY(Srf -> UKnotVector, TV -> VKnotVector,
  381.                   sizeof(CagdRType) * (TV -> VLength +
  382.                            TV -> VOrder));
  383.         CAGD_GEN_COPY(Srf -> VKnotVector, TV -> WKnotVector,
  384.                   sizeof(CagdRType) * (TV -> WLength +
  385.                            TV -> WOrder));
  386.         }
  387.         else {
  388.         Srf = BzrSrfNew(TV -> VLength, TV -> WLength, TV -> PType);
  389.         }
  390.         SrfLen = Srf -> ULength * Srf -> VLength;
  391.  
  392.         for (i = IsNotRational; i <= MaxCoord; i++) {
  393.         SrfP = Srf -> Points[i];
  394.         TVP = TV -> Points[i] + Index * TRIV_NEXT_U(TV);
  395.         for (j = 0; j < SrfLen; j++) {
  396.             *SrfP++ = *TVP;
  397.             TVP += TRIV_NEXT_V(TV);
  398.         }
  399.         }
  400.         break;
  401.     case TRIV_CONST_V_DIR:
  402.         if (Index >= TV -> VLength || Index < 0)
  403.         TRIV_FATAL_ERROR(TRIV_ERR_INDEX_NOT_IN_MESH);
  404.  
  405.         if (TV -> GType == TRIV_TVBSPLINE_TYPE) {
  406.         Srf = BspSrfNew(TV -> ULength, TV -> WLength,
  407.                 TV -> UOrder, TV -> WOrder,
  408.                 TV -> PType);
  409.         CAGD_GEN_COPY(Srf -> UKnotVector, TV -> UKnotVector,
  410.                   sizeof(CagdRType) * (TV -> ULength +
  411.                            TV -> UOrder));
  412.         CAGD_GEN_COPY(Srf -> VKnotVector, TV -> WKnotVector,
  413.                   sizeof(CagdRType) * (TV -> WLength +
  414.                            TV -> WOrder));
  415.         }
  416.         else {
  417.         Srf = BzrSrfNew(TV -> ULength, TV -> WLength, TV -> PType);
  418.         }
  419.         SrfLen = Srf -> ULength * Srf -> VLength;
  420.  
  421.         for (k = 0, i = IsNotRational; i <= MaxCoord; i++) {
  422.         SrfP = Srf -> Points[i];
  423.         TVP = TV -> Points[i]+ Index * TRIV_NEXT_V(TV);
  424.         for (j = 0; j < SrfLen; j++) {
  425.             *SrfP++ = *TVP;
  426.             TVP += TRIV_NEXT_U(TV);
  427.             if (++k == TV -> ULength) {
  428.             TVP += TRIV_NEXT_W(TV) - TRIV_NEXT_U(TV) * k;
  429.             k = 0;
  430.             }
  431.         }
  432.         }
  433.         break;
  434.     case TRIV_CONST_W_DIR:
  435.         if (Index >= TV -> WLength || Index < 0)
  436.         TRIV_FATAL_ERROR(TRIV_ERR_INDEX_NOT_IN_MESH);
  437.  
  438.         if (TV -> GType == TRIV_TVBSPLINE_TYPE) {
  439.         Srf = BspSrfNew(TV -> ULength, TV -> VLength,
  440.                 TV -> UOrder, TV -> VOrder,
  441.                 TV -> PType);
  442.         CAGD_GEN_COPY(Srf -> UKnotVector, TV -> UKnotVector,
  443.                   sizeof(CagdRType) * (TV -> ULength +
  444.                            TV -> UOrder));
  445.         CAGD_GEN_COPY(Srf -> VKnotVector, TV -> VKnotVector,
  446.                   sizeof(CagdRType) * (TV -> VLength +
  447.                            TV -> VOrder));
  448.         }
  449.         else {
  450.         Srf = BzrSrfNew(TV -> ULength, TV -> VLength, TV -> PType);
  451.         }
  452.         SrfLen = Srf -> ULength * Srf -> VLength;
  453.  
  454.         for (i = IsNotRational; i <= MaxCoord; i++) {
  455.         SrfP = Srf -> Points[i];
  456.         TVP = TV -> Points[i]+ Index * TRIV_NEXT_W(TV);
  457.         for (j = 0; j < SrfLen; j++) {
  458.             *SrfP++ = *TVP;
  459.             TVP += TRIV_NEXT_U(TV);
  460.         }
  461.         }
  462.         break;
  463.     default:
  464.         TRIV_FATAL_ERROR(TRIV_ERR_WRONG_DOMAIN);
  465.         break;
  466.     }
  467.     return Srf;
  468. }
  469.  
  470. /*****************************************************************************
  471. * DESCRIPTION:                                                               M
  472. * Substitute a bivariate surface into a given trivariate's mesh.         M
  473. *   The provided (zero based) Index specifies which Index to extract.        M
  474. *                                                                            *
  475. * PARAMETERS:                                                                M
  476. *   Srf:       Surface to substitute into the trivariate TV.             M
  477. *   Index:     Index of row/column/level of TV's mesh in direction Dir.      M
  478. *   Dir:       Direction of isosurface extraction. Either U or V or W.       M
  479. *   TV:        Trivariate to substitute a bivariate surface into its mesh.   M
  480. *                                                                            *
  481. * RETURN VALUE:                                                              M
  482. *   void                                                                 M
  483. *                                                                            *
  484. * KEYWORDS:                                                                  M
  485. *   TrivSrfToMesh, trivariates                                               M
  486. *****************************************************************************/
  487. void TrivSrfToMesh(CagdSrfStruct *Srf,
  488.            int Index,
  489.            TrivTVDirType Dir,
  490.            TrivTVStruct *TV)
  491. {
  492.     CagdBType
  493.     IsNotRational = !TRIV_IS_RATIONAL_TV(TV);
  494.     int i, j, k,
  495.     SrfLen = Srf -> ULength * Srf -> VLength,
  496.     MaxCoord = CAGD_NUM_OF_PT_COORD(TV -> PType);
  497.     CagdRType *SrfP, *TVP;
  498.  
  499.     switch (Dir) {
  500.     case TRIV_CONST_U_DIR:
  501.         if (Index >= TV -> ULength || Index < 0)
  502.         TRIV_FATAL_ERROR(TRIV_ERR_INDEX_NOT_IN_MESH);
  503.  
  504.         for (i = IsNotRational; i <= MaxCoord; i++) {
  505.         SrfP = Srf -> Points[i];
  506.         TVP = TV -> Points[i] + Index * TRIV_NEXT_U(TV);
  507.         for (j = 0; j < SrfLen; j++) {
  508.             *TVP = *SrfP++;
  509.             TVP += TRIV_NEXT_V(TV);
  510.         }
  511.         }
  512.         break;
  513.     case TRIV_CONST_V_DIR:
  514.         if (Index >= TV -> VLength || Index < 0)
  515.         TRIV_FATAL_ERROR(TRIV_ERR_INDEX_NOT_IN_MESH);
  516.  
  517.         for (k = 0, i = IsNotRational; i <= MaxCoord; i++) {
  518.         SrfP = Srf -> Points[i];
  519.         TVP = TV -> Points[i]+ Index * TRIV_NEXT_V(TV);
  520.         for (j = 0; j < SrfLen; j++) {
  521.             *TVP = *SrfP++;
  522.             TVP += TRIV_NEXT_U(TV);
  523.             if (++k == TV -> ULength) {
  524.             TVP += TRIV_NEXT_W(TV) - TRIV_NEXT_U(TV) * k;
  525.             k = 0;
  526.             }
  527.         }
  528.         }
  529.         break;
  530.     case TRIV_CONST_W_DIR:
  531.         if (Index >= TV -> WLength || Index < 0)
  532.         TRIV_FATAL_ERROR(TRIV_ERR_INDEX_NOT_IN_MESH);
  533.  
  534.         for (i = IsNotRational; i <= MaxCoord; i++) {
  535.         SrfP = Srf -> Points[i];
  536.         TVP = TV -> Points[i]+ Index * TRIV_NEXT_W(TV);
  537.         for (j = 0; j < SrfLen; j++) {
  538.             *TVP = *SrfP++;
  539.             TVP += TRIV_NEXT_U(TV);
  540.         }
  541.         }
  542.         break;
  543.     default:
  544.         TRIV_FATAL_ERROR(TRIV_ERR_WRONG_DOMAIN);
  545.         break;
  546.     }
  547. }
  548.  
  549.